Hill2密码加解密及破译的C语言实现

加解密部分代码参考这位老哥Hill密码的加密与解密,做了相应的一些修改,需要注意的是代码中有两个问题尚待解决:

1.代码中补全位没有起到相应作用,如果输入明文为奇数则无法正常加解密。

2.当选取的密钥矩阵求逆后有小数元,无法实现正确解密。

代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 60

int main()
{
    int K1[2][2] = {0}, K2[2][2] = {0};
    int Temp1[2] = {0}, Temp2[2] = {0};
    char P[N] = {0}, C[N] = {0};
    int T1[N] = {0}, T2[N] = {0};
    int len, flag=0, temp, temp1, i, j;


    printf("Hill2密码\n\n");
    printf("请依次输入密钥矩阵的值:\n");
    
    for(i=0; i<2; i++)  //存储密钥 
    {
        for(j=0; j<2; j++)
        {
            scanf("%d", &K1[i][j]);
        }
    }

        //输入明文 
        printf("请输入明文:\n");
        scanf("%s", P);
        len = strlen(P);

        // 当长度为奇数时补齐一位
        if(len % 2 == 1)
        {
            P[len] = 'a';
            len = strlen(P);
            flag = 1;
        }

        // 将大写转成小写,并赋值给T1数组
        for(i=0; i<len; i++)
        {
            if(P[i] >= 'A' && P[i] <= 'Z')
            {
                P[i] = P[i] + 32;
            }

            T1[i] = P[i] - 'a';
        }


        // 得到加密后结果,存储在T2中
        for(i=0; i<len; i+=2)
        {
            Temp1[0] = T1[i];
            Temp1[1] = T1[i + 1];

            // Temp2存储密文int值
            Temp2[0] = (Temp1[0] * K1[0][0] + Temp1[1] * K1[1][0]) % 26;
            Temp2[1] = (Temp1[0] * K1[0][1] + Temp1[1] * K1[1][1]) % 26;

            T2[i] = Temp2[0];
            T2[i + 1] = Temp2[1];
        }

        //如果有补全位,输出时去掉补全位 
        if(flag == 1) 
        {
            len = len - 1;
        }

        printf("加密结果为:\n");
        for(i=0; i<len; i++)
        {
            C[i] = T2[i] + 'a';
            printf("%c ", C[i]);
        }
        printf("\n");
    

        //解密 
        printf("请输入密文:\n");
        scanf("%s", C);

        len = strlen(C);

        // 当长度为奇数时补齐一位
        if(len % 2 == 1)
        {
            C[len] = 'a';
            len = strlen(C);
            flag = 1;
        }

        //大小写转换 
        for(i=0; i<len; i++)
        {
            if(C[i] >= 'A' && C[i] <= 'Z')
            {
                C[i] = C[i] + 32;
            }

            T2[i] = C[i] - 'a';
        }

        // 求K的逆
        temp = -1;
        for(i=1; temp < 0; i++)
        {
            temp = (K1[0][0] * K1[1][1] - K1[0][1] * K1[1][0]) + 26 * i;
        }

        i = 1;
        while(1)
        {
            if((temp * i) % 26 == 1)
            {
                temp1 = i;
                break;
            }
            else
            {
                i++;
            }
        }

        K2[0][0] = K1[1][1] * temp1;
        K2[0][1] = (((-1 * K1[0][1]) + 26) * temp1) % 26;
        K2[1][0] = (((-1 * K1[1][0]) + 26) * temp1) % 26;
        K2[1][1] = K1[0][0] * temp1;


        // 得到解密后结果,存储在T2中
        for(i=0; i<len; i+=2)
        {
            Temp2[0] = T2[i];
            Temp2[1] = T2[i + 1];

            // Temp1存储明文int值
            Temp1[0] = (Temp2[0] * K2[0][0] + Temp2[1] * K2[1][0]) % 26;
            Temp1[1] = (Temp2[0] * K2[0][1] + Temp2[1] * K2[1][1]) % 26;

            T1[i] = Temp1[0];
            T1[i + 1] = Temp1[1];
        }

        if(flag == 1)
        {
            len = len - 1;
        }

        printf("解密结果为:\n");
        for(i=0; i<len; i++)
        {
            P[i] = T1[i] + 'a';
            printf("%c ", P[i]);
        }
        printf("\n"); 
        
    return 0;
}
 

破译原理网上很多利用,利用矩阵运算,再此不赘述,直接放上代码,和加解密一样,明文矩阵的逆若有小数元无法实现正常破译。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h> 
#define N 60

int main()
{
    int K[2][2] = {0};
    int Temp1[2] = {0}, Temp2[2] = {0};
    char c[N]={0},m[N]={0},_c[N]={0};
    int T1[N] = {0}, T2[N] = {0};
    int lenc,lenm,temp,temp1,i,j; 

    printf("破译Hill2密码\n\n");

        //输入已知明文段 
        printf("请输入已知明文:\n");
        scanf("%s", c);
        lenc = strlen(c);
         //输入已知密文段 
        printf("请输入已知密文:\n");
        scanf("%s", m);
        lenm= strlen(m);

        //当明密文长度不足4时报错 
        if(lenc<4||lenm<4)
        {
        	printf("明密文字段不满足破译条件");
        	assert(0);
        }

        //取前四位明文,将大写转成小写,并赋值给T1数组 
        for(i=0; i<4; i++)
        {
            if(c[i] >= 'A' && c[i] <= 'Z')
            {
                c[i] = c[i] + 32;
            }

            T1[i] = c[i] - 'a';
        }
        //取前四位密文,将大写转成小写,并赋值给T2数组
        for(i=0; i<4; i++)
        {
            if(m[i] >= 'A' && m[i] <= 'Z')
            {
                m[i] = m[i] + 32;
            }

            T2[i] = m[i] - 'a';
        }
        // 求明文数组的逆
        temp = -1;
        for(i=1; temp < 0; i++)
        {
            temp = (T1[0]*T1[3]-T1[1]*T1[2]) + 26 * i;
        }

        i = 1;
        while(1)
        {
            if((temp*i)%26==1)
            {
                temp1 = i;
                break;
            }
            else
            {
                i++;
            }
        }

        _c[0]=(T1[3]*temp1)%26;
        _c[1]=(((-1*T1[1]+26))*temp1)%26;
        _c[2]=(((-1*T1[2]+26))*temp1)%26;
        _c[3]=(T1[0]*temp1)%26;
        
        //密文矩阵右乘明文逆矩阵 
        K[0][0]=(T2[0]*_c[0]+T2[2]*_c[1])%26;
        K[0][1]=(T2[1]*_c[0]+T2[3]*_c[1])%26;
        K[1][0]=(T2[0]*_c[2]+T2[2]*_c[3])%26;
        K[1][1]=(T2[1]*_c[2]+T2[3]*_c[3])%26;
		 
        printf("密钥为:");
        for(i=0;i<2;i++)
		{
			for(j=0;j<2;j++)
			{
				printf("%d ",K[i][j]);
			}
		 } 
    
    return 0;
}
 

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hill密码是一种基于线性代数的密码算法,可以用矩阵加密和解密。以下是Hill密码的Python实现: 加密: ```python import numpy as np # 明文转化为数字 def char2num(char): return ord(char.lower()) - 97 # 数字转化为明文 def num2char(num): return chr(num + 97) # 将明文转化为矩阵 def plaintext2matrix(plaintext, n): plaintext = plaintext.lower().replace(' ', '') plaintext_len = len(plaintext) matrix_len = (plaintext_len // n + (plaintext_len % n != 0)) * n matrix = np.zeros((matrix_len,), dtype=int) matrix[:plaintext_len] = [char2num(char) for char in plaintext] return matrix.reshape(-1, n) # 将矩阵转化为密文 def matrix2ciphertext(matrix, key): return np.dot(matrix, key) % 26 # Hill加密 def hill_encrypt(plaintext, key): n = key.shape[0] matrix = plaintext2matrix(plaintext, n) ciphertext_matrix = matrix2ciphertext(matrix, key) ciphertext = ''.join([num2char(num) for num in ciphertext_matrix.flatten()]) return ciphertext ``` 解密: ```python # 求解矩阵的逆 def matrix_inverse(matrix): det = np.linalg.det(matrix) inv_det = pow(int(det), -1, 26) adj_matrix = np.array([[pow(-1, i+j)*np.linalg.det(np.delete(np.delete(matrix, i, axis=0), j, axis=1)) for j in range(matrix.shape[1])] for i in range(matrix.shape[0])], dtype=int) inv_matrix = (inv_det * adj_matrix) % 26 return inv_matrix # 将密文转化为矩阵 def ciphertext2matrix(ciphertext, n): ciphertext_len = len(ciphertext) matrix_len = (ciphertext_len // n + (ciphertext_len % n != 0)) * n matrix = np.zeros((matrix_len,), dtype=int) matrix[:ciphertext_len] = [char2num(char) for char in ciphertext] return matrix.reshape(-1, n) # 将矩阵转化为明文 def matrix2plaintext(matrix): return ''.join([num2char(num) for num in matrix.flatten()]) # Hill解密 def hill_decrypt(ciphertext, key): n = key.shape[0] inv_key = matrix_inverse(key) ciphertext_matrix = ciphertext2matrix(ciphertext, n) plaintext_matrix = matrix2ciphertext(ciphertext_matrix, inv_key) plaintext = matrix2plaintext(plaintext_matrix) return plaintext ``` 使用示例: ```python # 加密 plaintext = 'hello world' key = np.array([[3, 2], [1, 4]]) ciphertext = hill_encrypt(plaintext, key) print(ciphertext) # 解密 plaintext = hill_decrypt(ciphertext, key) print(plaintext) ``` 输出: ``` fjqzvbtwvv helloworld ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值